package com.iwhalecloud.bss.kite.cucc.service.goods;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.iwhalecloud.bss.hsf.baseinf.service.InfExchangeService;
import com.iwhalecloud.bss.kite.common.util.KiteListUtils;
import com.iwhalecloud.bss.kite.common.util.KiteMapUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.cucc.client.api.goods.IGoodsPriceFactorService;
import com.iwhalecloud.bss.kite.cucc.client.api.inf.IInfServiceBus;
import com.iwhalecloud.bss.kite.cucc.client.dto.goods.GoodPriceReqDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.goods.factor.FeePriceFactorDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.goods.factor.GoodsPriceFactorReqDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.goods.factor.GoodsPriceFactorRspDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.goods.factor.PriceFactorDTO;
import com.iwhalecloud.bss.kite.cucc.common.callclient.HttpsCallClient;
import com.iwhalecloud.bss.kite.cucc.common.constant.LocalCallClientEnum;
import com.iwhalecloud.bss.kite.cucc.dataservice.cache.CityTypeCodeCache;
import com.iwhalecloud.bss.kite.cucc.dataservice.cache.PriceFactorsCache;
import com.iwhalecloud.bss.kite.cucc.service.inf.InfServiceHelper;
import com.iwhalecloud.bss.kite.cucc.service.util.CallClientUtils;
import com.iwhalecloud.bss.kite.cucc.service.util.GoodsPriceFactorUtil;
import com.iwhalecloud.bss.kite.cucc.service.util.LocalTokenUtil;
import com.iwhalecloud.bss.kite.dataservice.cache.ProdFeeCache;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.Offer;
import com.iwhalecloud.bss.kite.manager.enums.ActionType;
import com.iwhalecloud.bss.kite.manager.enums.InstType;
import com.iwhalecloud.bss.kite.manager.inst.KiteOfferInst;
import com.ztesoft.bss.common.util.SpringUtil;

@Service
public class GoodsPriceFactorService implements IGoodsPriceFactorService {

    private static final String GOODS_PRICE_FACTOR_OP_CODE = "json_chinaUnicom_govEnterprise_proCoCenter_getGoodsPriceFactor";

    private static Map<String, String> CITY_TYPE_MAPPINGS;

    @Autowired
    private IInfServiceBus infServiceBus;

    static {
        CITY_TYPE_MAPPINGS = new HashMap<>();
        CITY_TYPE_MAPPINGS.put("110010217", "一类城市");
        CITY_TYPE_MAPPINGS.put("110010218", "二类城市");
        CITY_TYPE_MAPPINGS.put("110010219", "其他城市");
    }

    @Override
    public GoodsPriceFactorRspDTO qryGoodsPriceFactor(GoodsPriceFactorReqDTO goodsPriceFactorReqDTO) {
        Map<String, Object> uniBssBody = new HashMap<>();
        Map<String, Object> goodsPriceFactorReq = KiteMapUtils.beanToMap(goodsPriceFactorReqDTO);
        uniBssBody.put("GET_GOODS_PRICE_FACTOR_REQ", goodsPriceFactorReq);
        Map<String, Object> param = LocalTokenUtil.getParamMap(uniBssBody);
        param.put("OP_CODE", GOODS_PRICE_FACTOR_OP_CODE);
        InfServiceHelper.adaptGray(param, goodsPriceFactorReq);
        String resultStr;
        if (CallClientUtils.callByHttp()) {
            resultStr = HttpsCallClient.postStringWithObject(LocalCallClientEnum.INF_COMMON_URL.getCenterCode(),
                LocalCallClientEnum.INF_COMMON_URL.getServiceCode(), param, LocalTokenUtil.getHeaderMap());
        }
        else {
            InfExchangeService infExchangeService = SpringUtil.getBean("infExchangeService");
            resultStr = infExchangeService.exchange(new JSONObject(param));
        }
        if (KiteStringUtils.isEmpty(resultStr)) {
            return null;
        }
        if (!resultStr.contains("GET_GOODS_PRICE_FACTOR_RSP")) {
            return null;
        }
        Map<String, Object> result = JSON.parseObject(resultStr, Map.class);
        Map<String, Object> resultBodyMap = (Map<String, Object>) result.get("UNI_BSS_BODY");
        Map<String, Object> goodsPriceFactorRsp = (Map<String, Object>) resultBodyMap.get("GET_GOODS_PRICE_FACTOR_RSP");
        GoodsPriceFactorRspDTO goodsPriceFactorRspDTO = new GoodsPriceFactorRspDTO();
        boolean success = KiteMapUtils.getValue(goodsPriceFactorRsp,"success");
        if (success){
            goodsPriceFactorRspDTO = JSONObject.parseObject(JSON.toJSONString(goodsPriceFactorRsp.get("data")), GoodsPriceFactorRspDTO.class);
        }
        return goodsPriceFactorRspDTO;
    }

    @Override
    public List<PriceFactorDTO> getPriceFactors(String goodSku) {
        return this.getPriceFactors(goodSku, null);
    }

    @Override
    public List<PriceFactorDTO> getPriceFactors(String goodSku, String feeCode) {
        List<PriceFactorDTO> allPriceFactor = new ArrayList<>();
        if (KiteStringUtils.isNotEmpty(feeCode)) {
            Optional.ofNullable(PriceFactorsCache.get(feeCode)).ifPresent(allPriceFactor::addAll);
        } else {
            Optional.ofNullable(PriceFactorsCache.get(goodSku)).ifPresent(allPriceFactor::addAll);
        }
        if (KiteListUtils.isNotEmpty(allPriceFactor)) {
            return allPriceFactor;
        }
        GoodsPriceFactorReqDTO goodsPriceFactorReqDTO = new GoodsPriceFactorReqDTO();
        goodsPriceFactorReqDTO.setGoodsSku(goodSku);
        goodsPriceFactorReqDTO.setFeeCodes(Objects.isNull(feeCode) ? null : Lists.newArrayList(feeCode));
        GoodsPriceFactorRspDTO goodsPriceFactors = this.qryGoodsPriceFactor(goodsPriceFactorReqDTO);
        if(goodsPriceFactors != null) {
            List<FeePriceFactorDTO> feePriceFactors = goodsPriceFactors.getFeePriceFactors();
            if (KiteListUtils.isNotEmpty(feePriceFactors)) {
                feePriceFactors.forEach(feePriceFactor -> {
                    List<PriceFactorDTO> priceFactors = feePriceFactor.getPriceFactors();
                    if (KiteListUtils.isNotEmpty(priceFactors)) {
                        priceFactors.forEach(priceFactor -> {
                            if (!allPriceFactor.stream().anyMatch(all -> KiteStringUtils.equals(priceFactor.getAttrCode(), all.getAttrCode()))) {
                                allPriceFactor.add(priceFactor);
                            }
                        });
                    }
                });
                // 缓存计价因子
                String cacheKey = KiteStringUtils.isNotEmpty(feeCode) ? feeCode : goodSku;
                PriceFactorsCache.delayPut(cacheKey, allPriceFactor);
            }
        }
        return allPriceFactor;
    }

    /**
     * 获取套餐下资费对应的价格
     * @param sceneInstId
     * @param custId
     * @param mainOfferId
     * @param additionalOfferInst
     * @return
     */
    public Map<String, Object> getFeeProdPrice(String sceneInstId, String custId, String mainOfferId, KiteOfferInst additionalOfferInst) {
        // 不是新增资费不进行算价
        if (!InstType.ADDITIONAL_OFFER_INST.equals(additionalOfferInst.getInstType()) || !ActionType.A.equals(additionalOfferInst.getActionType())) {
            return null;
        }
        Map<String, Object> offerMap = Optional.ofNullable(ProdFeeCache.get(additionalOfferInst.getSpecId())).map(Offer::getOfferMap).orElse(null);
        if (Objects.isNull(offerMap)) {
            return null;
        }
        String feeCode = KiteMapUtils.getString(offerMap, "discntCode");
        GoodPriceReqDTO goodPriceReq = new GoodPriceReqDTO();
        goodPriceReq.setSKU(mainOfferId);
        // 取到当前套餐下资费的计价因子列表
        List<PriceFactorDTO> priceFactors = this.getPriceFactors(mainOfferId, feeCode);
        GoodsPriceFactorUtil.transform(goodPriceReq, priceFactors);
        GoodsPriceFactorUtil.fillAttrValue(sceneInstId, custId, goodPriceReq, priceFactors);
        if (KiteListUtils.isEmpty(goodPriceReq.getPropertyValue())
            || goodPriceReq.getPropertyValue().stream().allMatch(attr -> KiteStringUtils.isEmpty(attr.getAttrVal()))) {
            return null;
        }
        Map<String, Object> goodPrice = infServiceBus.queryGoodPrice(goodPriceReq).getResultObject();
        return goodPrice;
    }

    @Override
    public String getCityTypeCode(String provinceCode, String cityCode) {
        String cityTypeCode = "";
        List<Map<String, Object>> regionList = CityTypeCodeCache.get(provinceCode);
        if (KiteListUtils.isNotEmpty(regionList)) {
            for (Map<String, Object> region : regionList) {
                if (KiteStringUtils.equals(KiteMapUtils.getString(region, "AREA_CODE"), cityCode)) {
                    cityTypeCode = getCityTypeCode(KiteMapUtils.getString(region, "CITY_TYPE_NAME"));
                }
            }
        }
        return cityTypeCode;
    }

    private static String getCityTypeCode(String cityTypeName) {
        String result = "";
        Iterator<String> iterator = CITY_TYPE_MAPPINGS.keySet().iterator();
        while (iterator.hasNext()) {
            String key = iterator.next();
            String value = CITY_TYPE_MAPPINGS.get(key);
            if (KiteStringUtils.equals(value, cityTypeName)) {
                result = key;
            }
        }
        return result;
    }
}
